package com.pbase.data.http.upanddown;

import android.webkit.MimeTypeMap;

import com.pbase.data.http.RetrofitBuilderTool;
import com.pbase.data.http.listener.OnDataRequestListenerWithProgress;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import androidx.annotation.NonNull;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.observers.DisposableObserver;
import io.reactivex.rxjava3.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
import retrofit2.http.PartMap;
import retrofit2.http.Url;

/**
 * 文件上传管理 先这么写，后面看看进度条怎么补
 */
public class UpRetrofitClient {

    private static Retrofit retrofit;
    private OnDataRequestListenerWithProgress listener;
    private DisposableObserver<ResponseBody> disposable;

    public UpRetrofitClient() {
    }


    public void retrofitClient(@NonNull RetrofitBuilderTool tool,
                               OnDataRequestListenerWithProgress listener) {
        this.listener = listener;
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .connectTimeout(tool.connectTimeout(), TimeUnit.SECONDS)
                .readTimeout(tool.readTimeout(), TimeUnit.SECONDS)
                .writeTimeout(tool.writeTimeout(), TimeUnit.SECONDS);
        OkHttpClient okHttpClient = builder.build();

        retrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                .baseUrl(tool.baseUrl())
                .build();
    }

    public void upload(String url, Map<String, String> params, List<File> files) {
        retrofit.create(UpServer.class).upload(url, convertToRequestBody(params),
                convertToMultipartBody(files))
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(listener );

    }

    public Map<String, RequestBody> convertToRequestBody(Map<String, String> map) {
        if (map == null) {
            return null;
        }
        Map<String, RequestBody> bodyMap = new HashMap<>();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            bodyMap.put(key, RequestBody.create(value, MediaType.Companion.parse("text/plain")));
        }
        return bodyMap;
    }

    public List<MultipartBody.Part> convertToMultipartBody(List<File> files) {
        if (files == null) {
            return null;
        }
        List<MultipartBody.Part> bodyList = new ArrayList<>();
        for (File file : files) {

            MultipartBody.Part part = MultipartBody.Part.createFormData("file_name", file.getName(),
                    RequestBody.create(file,
                            MediaType.Companion.parse(getMimeType(file.getPath()))));
            bodyList.add(part);
        }
        return bodyList;

    }

    public static String getMimeType(String url) {
        String type = null;
        String extension = MimeTypeMap.getFileExtensionFromUrl(url);
        if (extension != null) {
            type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
        }
        return type.toLowerCase();
    }

    /**
     * 停止上传
     */
    public void stopUp() {
        if (disposable != null && !disposable.isDisposed()) {
            disposable.dispose();
        }
        disposable = null;
    }

    private interface UpServer {
        @POST
        @Multipart
//表示请求体是一个支持文件上传的Form表单
        Observable<String> upload(@Url String url, @PartMap Map<String, RequestBody> map,
                                        @Part List<MultipartBody.Part> parts);
    }
}
